package com.xiaomacdut.oauthgithub.util;

import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;



/**
 * @date 2019年5月5日 下午1:52:12
 */
@SuppressWarnings("restriction")
public class HttpsUtil{

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpsUtil.class);

    /** 链接超时时间(单位：ms) */
    private static int connectionTimeOut = 120000;
    /** 请求超时时间(单位：ms) */
    private static int requestTimeOut = 120000;

    /** 系统默认编码 **/
    public static final String UTF_8 = "UTF-8";

    /**
     * 无参构造
     */
    private HttpsUtil(){}

    /** HTTPClient配置 */
    private static RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(connectionTimeOut).setConnectTimeout(connectionTimeOut).setConnectionRequestTimeout(requestTimeOut).build();


    public static String get(String url, String token,String reqCharSet, String reponseCharSet){
        HttpGet httpget = new HttpGet(url);
        httpget.addHeader("Authorization","token "+token);
        CloseableHttpClient httpClient = createSSLClientDefault();
        return excuteMethod(httpClient, httpget, url, reqCharSet, reponseCharSet);
    }

    public static String post(String url, Map<String, String> paramsMap, String reqCharSet, String reponseCharSet){
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        CloseableHttpClient httpClient = createSSLClientDefault();
        if(!CollectionUtils.isEmpty(paramsMap)){
            for(Map.Entry<String, String> vo : paramsMap.entrySet()){
                params.add(new BasicNameValuePair(vo.getKey(), vo.getValue()));
            }
        }

        try{
            httpPost.setEntity(new UrlEncodedFormEntity(params, reqCharSet));
        }catch(UnsupportedEncodingException e){
            LOGGER.info("编码格式错误{}", e);
        }
        return excuteMethod(httpClient, httpPost, url, reqCharSet, reponseCharSet);
    }


    private static String excuteMethod(HttpClient httpClient, HttpRequestBase method, String url, String reqCharSet, String reponseCharSet){
        HttpResponse httpResponse = null;
        String responseBody = "";
        SendResult result = new SendResult();

        String reqTempCharSet = reqCharSet;
        String reponseTempCharSet = reponseCharSet;
        if(StringUtils.isEmpty(reqTempCharSet)){
            reqTempCharSet = HttpsUtil.UTF_8;
        }
        if(StringUtils.isEmpty(reponseTempCharSet)){
            reponseTempCharSet = HttpsUtil.UTF_8;
        }

        try{
            httpResponse = httpClient.execute(method);
            HttpEntity httpEntity = httpResponse.getEntity();
            StatusLine status = httpResponse.getStatusLine();
            int statusCode = status.getStatusCode();
            result.setCode(String.valueOf(statusCode));
            if(HttpStatus.SC_OK != statusCode){
                LOGGER.info("/**********返回状态码{}*********/", statusCode);
            }
            if(httpEntity != null){
                responseBody = EntityUtils.toString(httpEntity, reponseTempCharSet);
                result.setResult(responseBody);
            }
            return JsonUtil.toJSONString(result);
        }catch(Exception e){
            LOGGER.error("/********POST请求异常:{}********/", e);
        }finally{
            if(method!=null){
                method.releaseConnection();
            }

        }

        return responseBody;
    }

    /**
     * createSSLClientDefault
     * @return
     * @version 0.0.1
     * @since 0.0.1
     * @data 2019年5月5日 下午2:06:16
     */
    public static CloseableHttpClient createSSLClientDefault(){

        // 设置到相应参数
        /*        RequestConfig defaultRequestConfig = RequestConfig.custom().setConnectTimeout(connectionTimeOut).// 连接时间20s
                setSocketTimeout(requestTimeOut).// 数据传输时间60s
                build();*/

        try{
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy(){

                // 信任所有
                public boolean isTrusted(X509Certificate [] chain, String authType) throws CertificateException{
                    return true;
                }
            }).build();
            HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new String[]{"TLSv1.2", "TLSv1", "TLSv1.1"}, new String[]{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"},
                    hostnameVerifier);
            return HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(requestConfig).build();
        }catch(KeyManagementException e){
            LOGGER.error("/********POST请求异常********/", e);
        }catch(NoSuchAlgorithmException e){
            LOGGER.error("/********POST请求异常********/", e);
        }catch(KeyStoreException e){
            LOGGER.error("/********POST请求异常********/", e);
        }
        return null;
    }

}
